from typing import Dict, Any, Optional, TypeVar, Union, overload

from chernc.treediff.gumtree.matchers.configuration_options import ConfigurationOptions

T = TypeVar("T", str, int, float)
class GumtreeProperties:
    def __init__(self) -> None:
        self.properties: Dict[str, Union[str, int, float]] = {}

    def put(self, option: 'ConfigurationOptions', value: Union[str, int, float]) -> None:
        if option is not None:
            self.properties[option.name] = value

    def get(self, option: 'ConfigurationOptions') -> Optional[Union[str, int, float]]:
        if option is not None:
            return self.properties.get(option.name)
        return None

    def _set_if_not_present(self, property_name: str, value: Union[str, int, float]) -> Union[str, int, float]:
        if property_name not in self.properties:
            self.properties[property_name] = value
            return value
        return self.properties[property_name]

    @overload
    def try_configure(self, property_name: 'ConfigurationOptions', value: str) -> str:
        ...

    @overload
    def try_configure(self, property_name: 'ConfigurationOptions', value: int) -> int:
        ...

    @overload
    def try_configure(self, property_name: 'ConfigurationOptions', value: float) -> float:
        ...

    def try_configure(self, property_name: 'ConfigurationOptions', value: T) -> T:
        if isinstance(value, str):
            return self._try_configure_string(property_name.name, value)
        elif isinstance(value, int):
            return self._try_configure_int(property_name.name, value)
        elif isinstance(value, float):
            return self._try_configure_float(property_name.name, value)
        else:
            raise TypeError("Unsupported value type")

    def _try_configure_string(self, property_name: str, value: str) -> str:
        property_value = self._set_if_not_present(property_name, value)
        if property_value is not None:
            return str(property_value)
        return value

    def _try_configure_int(self, property_name: str, value: int) -> int:
        property_value = self._set_if_not_present(property_name, value)
        if property_value is not None:
            try:
                return int(property_value)
            except Exception as e:
                raise ValueError(e)
        return value

    def _try_configure_float(self, property_name: str, value: float) -> float:
        property_value = self._set_if_not_present(property_name, value)
        if property_value is not None:
            try:
                return float(property_value)
            except Exception as e:
                raise ValueError(e)
        return value

    def __str__(self) -> str:
        return ", ".join(f"{key}={value}" for key, value in self.properties.items())